package com.dormitory.management.system.service.impl;

import com.alibaba.excel.EasyExcel;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.dormitory.management.system.DAO.UpLoadStudentExcelFileDao;
import com.dormitory.management.system.entity.*;
import com.dormitory.management.system.enums.StudentEnum;
import com.dormitory.management.system.enums.UserEnum;

import com.dormitory.management.system.listener.UpLoadStudentExcelFileListener;
import com.dormitory.management.system.mapper.*;
import com.dormitory.management.system.req.*;
import com.dormitory.management.system.resp.StuAndHouResp;
import com.dormitory.management.system.resp.StudentCheckInOutResp;
import com.dormitory.management.system.service.StudentService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.dormitory.management.system.service.UserRoleService;
import com.dormitory.management.system.service.UserService;
import com.dormitory.management.system.utils.EmailUtil;
import com.dormitory.managemnet.util.core.Result;
import com.dormitory.managemnet.util.utils.BeanUtil;
import org.checkerframework.checker.units.qual.A;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 学生表 服务实现类
 * </p>
 *
 * @author
 * @since 2021-12-17
 */
@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private RoomMapper roomMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private StudentMapper studentMapper;
    @Autowired
    private RepairMapper repairMapper;
    @Autowired
    private LossMapper lossMapper;
    @Autowired
    private AccessMapper accessMapper;
    @Autowired
    private UpLoadStudentExcelFileDao upLoadStudentExcelFileDao;
    @Autowired
    private HousemasterMapper housemasterMapper;
    @Autowired
    private RedisTemplate redisTemplate;

    @Override
    @Transactional
    public Result save(StudentSaveReq req) {
        Student stu = this.baseMapper.selectOne(new QueryWrapper<Student>().lambda().eq(Student::getStuId, req.getStuId()));
        if(stu==null) {
            User user = new User();
            user.setUsername(req.getStuId());
            //密码初始为后6位
            user.setPassword(req.getStuId().substring(req.getStuId().length() - 6));
            //用户表插入
            if (userMapper.insert(user) > 0) {
                Student student = BeanUtil.copyProperties(req, Student.class);
                user = userMapper.selectOne(new QueryWrapper<User>().lambda().eq(User::getUsername, req.getStuId()));
                student.setId(user.getId());
                //学生表插入
                if (this.baseMapper.insert(student) > 0) {
                    //用户角色关联表插入
                    if(userRoleService.save(user.getId(), UserEnum.USER_STUDENT.getRoleId())) {
                        return Result.success("信息添加成功");
                    }
                    return Result.error("用户角色关联表添加失败");
                }
                return Result.error("学生信息添加失败");
            }
            return Result.error("用户信息添加失败");
        }
        return Result.error("该学生已存在，不可重复添加");
    }

    @Override
    @Transactional
    public boolean delete(Long id) {
        Student student = studentMapper.selectById(id);
        //学生表删除
        if(this.baseMapper.deleteById(id)>0){
            //用户表删除
            if(userMapper.deleteById(id)>0){
                //用户角色关联表删除
                if(userRoleService.delete(id)){
                    //房间信息更新
                    if (student.getRoomId()!=null) {
                        return roomMapper.update(null, new UpdateWrapper<Room>()
                                .setSql("current_number=current_number-1")
                                .eq("id", student.getRoomId())) > 0;
                    }
                    repairMapper.delete(new QueryWrapper<Repair>().lambda().eq(Repair::getStuId,student.getStuId()));
                    lossMapper.delete(new QueryWrapper<Loss>().lambda().eq(Loss::getUserId,student.getStuId()));
                    accessMapper.delete(new QueryWrapper<Access>().lambda().eq(Access::getStuId,student.getStuId()));
                    return true;
                }
                return false;
            }
            return false;
        }
        return false;
    }

    @Override
    @Transactional
    public boolean update(StudentUpdateReq req) {
        //更新学生表
        if(this.baseMapper.updateById(BeanUtil.copyProperties(req,Student.class))>0){
            User user = new User();
            user.setId(req.getId());
            user.setUsername(req.getStuId());
            user.setPassword(req.getStuId().substring(req.getStuId().length()-6));
            //更新用户表
            return userMapper.updateById(user)>0;
        }
        return false;
    }

    @Override
    public IPage<Student> getPage(StudentPageReq req) {
        Page<Student> page = new Page<>(req.getPageCurrent(),req.getPageSize());
        LambdaQueryWrapper<Student> lambda = new QueryWrapper<Student>().lambda()
                .like(req.getStuId()!=null,Student::getStuId,req.getStuId())
                .like(req.getName()!=null,Student::getName,req.getName())
                .eq(req.getSex()!=null,Student::getSex,req.getSex())
                .like(req.getMajor()!=null, Student::getMajor,req.getMajor())
                .like(req.getDepartment()!=null,Student::getDepartment,req.getDepartment())
                .like(req.getStuClass()!=null,Student::getStuClass,req.getStuClass());
        return this.baseMapper.selectPage(page, lambda);
    }

    @Override
    @Transactional
    public boolean checkInOut(StudentCheckInOutReq req) {
        //批量入住
        if(req.getStatus()== StudentEnum.STUDENT_CHECKIN.getStatusId()){
            for (int i = 0; i < req.getIdList().length; i++) {
                //学生信息更新
                this.baseMapper.update(null,new UpdateWrapper<Student>().lambda()
                        .set(Student::getRoomId,req.getRoomId())
                        .eq(Student::getId,req.getIdList()[i]));
                //房间信息更新
                roomMapper.update(null,new UpdateWrapper<Room>()
                        .setSql("current_number=current_number+1")
                        .eq("id",req.getRoomId()));
                //发送邮件
                sendMail(req.getIdList()[i],req.getUserId());
            }
            return true;
            //批量退住
        }else if (req.getStatus()==StudentEnum.STUDENT_CHECKOUT.getStatusId()){
            for (int i = 0; i < req.getIdList().length; i++) {
                //学生信息更新
                Student student = this.baseMapper.selectById(req.getIdList()[i]);
                this.baseMapper.update(null,new UpdateWrapper<Student>().lambda()
                        .set(Student::getRoomId,null)
                        .eq(Student::getId,req.getIdList()[i]));
                //房间信息更新
                roomMapper.update(null,new UpdateWrapper<Room>()
                        .setSql("current_number=current_number-1")
                        .eq("id",student.getRoomId()));
            }
            return true;
        }else
            return false;
    }

    @Override
    public IPage<StudentCheckInOutResp> getCheckInOutPage(StudentCheckInOutPageReq req) {
        //未入住学生列表
        if(req.getType()==StudentEnum.STUDENT_CHECKIN.getStatusId()) {
            return this.baseMapper.getIfCheckedStuInPage(new Page<>(req.getPageCurrent(), req.getPageSize()), new QueryWrapper<StudentCheckInOutResp>()
                    .eq("s.status_id",0)
                    .isNull("s.room_id")
                    .like(req.getStuId()!=null,"stu_id",req.getStuId())
                    .like(req.getName()!=null,"name",req.getName())
                    .like(req.getDepartment()!=null,"department",req.getDepartment())
                    .like(req.getMajor()!=null,"major",req.getMajor())
                    .like(req.getSex()!=null,"sex",req.getSex())
                    .like(req.getStuClass()!=null,"stu_class",req.getStuClass()));
        //已入住学生列表
        }else if(req.getType()==StudentEnum.STUDENT_CHECKOUT.getStatusId()){
            return this.baseMapper.getIfCheckedStuOutPage(new Page<>(req.getPageCurrent(), req.getPageSize()), new QueryWrapper<StudentCheckInOutResp>()
                    .eq("s.status_id",0)
                    .isNotNull("s.room_id")
                    .eq("s.room_id", req.getRoomId())
                    .like(req.getStuId()!=null,"stu_id",req.getStuId())
                    .like(req.getName()!=null,"s.name",req.getName())
                    .like(req.getDepartment()!=null,"s.department",req.getDepartment())
                    .like(req.getMajor()!=null,"s.major",req.getMajor())
                    .like(req.getSex()!=null,"s.sex",req.getSex())
                    .like(req.getStuClass()!=null,"s.stu_class",req.getStuClass()));
        }else
            return null;
    }


    @Override
    public Result importStudentByExcel(String username, MultipartFile file) throws IOException {
        if (!file.getResource().exists()){
            return Result.error("传入文件没有收到");
        }
        if (!"xlsx".equals(file.getOriginalFilename().split("\\.")[1])){
            return Result.error("请传入.xlsx格式文件");
        }
        /**
         * 通过阿里巴巴的EasyExcel进行excel文件和题库id的上传存储进数据库
         * UpLoadExcelFileListener监听器
         */
        EasyExcel.read(file.getInputStream(), StudentExcel.class, new UpLoadStudentExcelFileListener(upLoadStudentExcelFileDao,username)).sheet().doRead();
        return Result.success("excel导入成功");
    }

    //宿管分配学生寝室后发送
    private void sendMail(Long id,String userId){
        StuAndHouResp studentInfo = this.baseMapper.getStudentInfo(new QueryWrapper<StuAndHouResp>().eq("s.id", id));
        StuAndHouResp userInfo = userService.getUserInfo(userId);
        Email email = new Email(userInfo.getPhone(),userInfo.getName(),userService.getRoleKey(userId));
        String emailHou = studentInfo.getEmail();
        String name = studentInfo.getName();
        String identityCard = studentInfo.getStuId();
        String room=studentInfo.getLiving()+"-"+studentInfo.getBuilding()+"-"+studentInfo.getRoom();
        String content = email.assignToStu(name, identityCard, room);
        String subject="账号信息请查收";
        String filePath=null;
        redisTemplate.opsForValue().set(emailHou+"***"+subject+"***"+content+"***"+filePath,"dxc",10, TimeUnit.SECONDS);
    }
}
